package org.springmvc.web.servlet.mvc.method.annotation;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springmvc.constant.Constants;
import org.springmvc.web.context.WebApplicationContext;
import org.springmvc.web.method.HandlerMethod;
import org.springmvc.web.servlet.HandlerExecutionChain;
import org.springmvc.web.servlet.HandlerInterceptor;
import org.springmvc.web.servlet.HandlerMapping;
import org.springmvc.web.servlet.mvc.method.RequestMappingInfo;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author marin
 * @version 1.0
 * @date 2025/9/1 19:49
 * @desc 处理器映射器 专门为@RequestMapping注解服务处理的
 *       通过前端“请求”，来映射要执行的HandlerMethod
 */
@SuppressWarnings("all")
public class RequestMappingHandlerMapping implements HandlerMapping {

    private Map<RequestMappingInfo, HandlerMethod> handlerMap;

    public RequestMappingHandlerMapping(Map<RequestMappingInfo, HandlerMethod> handlerMap) {
        this.handlerMap = handlerMap;
    }

    /**
     * 其实就是根据请求路径、请求方式等映射处理器方法！
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        HandlerExecutionChain handlerExecutionChain = new HandlerExecutionChain();
        //添加拦截器
        ServletContext servletContext = request.getServletContext();
        WebApplicationContext webApplicationContext = (WebApplicationContext)servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT);
        List<HandlerInterceptor> interceptors = (List<HandlerInterceptor>)webApplicationContext.getBean(Constants.INTERCEPTORS);
        handlerExecutionChain.setInterceptorList(interceptors);
        //添加处理器方法对象
        String servletPath = request.getServletPath();
        String method = request.getMethod();
        RequestMappingInfo requestMappingInfo = new RequestMappingInfo(servletPath, method);
        HandlerMethod handlerMethod = handlerMap.get(requestMappingInfo);
        handlerExecutionChain.setHandler(handlerMethod);
        return handlerExecutionChain;
    }
}
